package com.example.easyexcel.service.impl;

import com.example.easyexcel.dao.AssetBasicInfoMapper;
import com.example.easyexcel.dao.AssetInterfaceApiInfoMapper;
import com.example.easyexcel.dao.AssetReportInfoMapper;
import com.example.easyexcel.dto.AssetBasicInfoDTO;
import com.example.easyexcel.dto.AssetInterfaceApiInfoDTO;
import com.example.easyexcel.dto.AssetReportDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class DataMigrationService {

    private final AssetReportInfoMapper assetReportInfoMapper;
    private final AssetBasicInfoMapper assetBasicInfoMapper;

    private final AssetInterfaceApiInfoMapper assetInterfaceApiInfoMapper;

    public DataMigrationService(AssetReportInfoMapper assetReportInfoMapper,
                                AssetBasicInfoMapper assetBasicInfoMapper,AssetInterfaceApiInfoMapper assetInterfaceApiInfoMapper) {
        this.assetReportInfoMapper = assetReportInfoMapper;
        this.assetInterfaceApiInfoMapper = assetInterfaceApiInfoMapper;
        this.assetBasicInfoMapper = assetBasicInfoMapper;
    }

    /**
     * 迁移数据从 asset_report_info 到 asset_basic_info
     */
    @Transactional
    public void migrateDataToAssetBasicInfo() {
        try {
            // 1. 查询需要迁移的数据
            // 1. 查询需要迁移的数据
            List<AssetReportDTO> reportInfos = assetReportInfoMapper.selectReportInfoForMigration();

            if (reportInfos.isEmpty()) {
                log.info("没有需要迁移的数据");
                return;
            }

            // 提取所有 reportName
            List<String> reportNames = reportInfos.stream()
                    .map(AssetReportDTO::getReportName)
                    .collect(Collectors.toList());

            // 将报表名称写入文本文件
            writeReportNamesToFile(reportNames, "report_names.txt");

            log.info("报表名称已成功写入到 report_names.txt 文件中");

            // 2. 转换数据
            List<AssetBasicInfoDTO> basicInfos = convertToAssetBasicInfo(reportInfos);

            // 3. 批量插入数据
            int result = assetBasicInfoMapper.insertBatch(basicInfos);

            log.info("数据迁移完成，成功迁移 {} 条数据", result);
        } catch (Exception e) {
            log.error("数据迁移失败: {}", e.getMessage(), e);
            throw new RuntimeException("数据迁移失败", e);
        }
    }

    /**
     * 将报表名称列表写入文本文件
     * @param reportNames 报表名称列表
     * @param fileName 文件名
     */
    private void writeReportNamesToFile(List<String> reportNames, String fileName) {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
            for (String reportName : reportNames) {
                writer.write(reportName);
                writer.newLine(); // 换行
            }
            log.info("成功将 " + reportNames.size() + " 个报表名称写入到 " + fileName);
        } catch (IOException e) {
            log.error("写入文件时发生错误", e);
            throw new RuntimeException("文件写入失败", e);
        }
    }

    /**
     * 转换数据格式
     */
    private List<AssetBasicInfoDTO> convertToAssetBasicInfo(List<AssetReportDTO> reportInfos) {
        List<AssetBasicInfoDTO> result = new ArrayList<>();

        for (AssetReportDTO reportInfo : reportInfos) {
            AssetBasicInfoDTO basicInfo = new AssetBasicInfoDTO();

            // 直接映射的字段
            basicInfo.setAssetNo(reportInfo.getAssetNo());
            basicInfo.setAssetName(reportInfo.getReportName()); // 使用 system_name 作为 asset_name
            basicInfo.setCreateTime(reportInfo.getCreateTime());
            basicInfo.setUpdateTime(reportInfo.getUpdateTime());

            // 设置默认值
            //
            basicInfo.setAssetTypeId(8L); // 默认资产类型ID
            basicInfo.setDataAssetSc(0); // 默认数据资产状态代码：已发布

            // 根据 system_name 设置业务主题域类型代码
            basicInfo.setBusinessThemeDomainTc(determineBusinessThemeDomain1(reportInfo.getReportName()));

            result.add(basicInfo);
        }

        return result;
    }

    /**
     * 迁移数据从 asset_interface_api_info 到 asset_basic_info
     */
    @Transactional
    public void migrateInterfaceApiDataToAssetBasicInfo() {
        try {
            // 1. 查询需要迁移的数据
            List<AssetInterfaceApiInfoDTO> interfaceApiInfos = assetInterfaceApiInfoMapper.selectInterfaceApiInfoForMigration();

            if (interfaceApiInfos.isEmpty()) {
                log.info("没有需要迁移的接口API数据");
                return;
            }

            // 提取所有 reportName
            List<String> interfaceNames = interfaceApiInfos .stream()
                    .map(AssetInterfaceApiInfoDTO::getInterfaceName)
                    .collect(Collectors.toList());

            // 将报表名称写入文本文件
            writeReportNamesToFile(interfaceNames, "interface_names.txt");

            log.info("报表名称已成功写入到 interface_names.txt 文件中");
            log.info("查询到 {} 条需要迁移的接口API数据", interfaceApiInfos.size());

            // 2. 转换数据
            List<AssetBasicInfoDTO> basicInfos = convertInterfaceApiToAssetBasicInfo(interfaceApiInfos);

            // 3. 批量插入数据
            int result = assetBasicInfoMapper.insertBatch(basicInfos);

            log.info("接口API数据迁移完成，成功迁移 {} 条数据", result);
        } catch (Exception e) {
            log.error("接口API数据迁移失败: {}", e.getMessage(), e);
            throw new RuntimeException("接口API数据迁移失败", e);
        }
    }

    /**
     * 转换接口API数据格式
     */
    private List<AssetBasicInfoDTO> convertInterfaceApiToAssetBasicInfo(List<AssetInterfaceApiInfoDTO> interfaceApiInfos) {
        List<AssetBasicInfoDTO> result = new ArrayList<>();

        for (AssetInterfaceApiInfoDTO apiInfo : interfaceApiInfos) {
            AssetBasicInfoDTO basicInfo = new AssetBasicInfoDTO();

            // 直接映射的字段
            basicInfo.setAssetNo(apiInfo.getAssetNo());
            basicInfo.setAssetName(apiInfo.getInterfaceName()); // 使用接口名称作为资产名称
            basicInfo.setCreateTime(apiInfo.getCreateTime());
            basicInfo.setUpdateTime(apiInfo.getUpdateTime());

            // 设置默认值
            basicInfo.setAssetTypeId(7L); // 接口API类型ID（与报表类型区分）
            //目前接口API里面没有状态，仍需要确认
            basicInfo.setDataAssetSc(0); // 默认数据资产状态代码：已发布，默认是0

            // 根据 system_name 设置业务主题域类型代码
            basicInfo.setBusinessThemeDomainTc(determineBusinessThemeDomain2(apiInfo.getInterfaceName()));

            result.add(basicInfo);
        }

        return result;
    }

    /**
     * 根据报表名称确定业务主题域类型代码
     * 0：参与者域；1：渠道域；2：乐透彩票域；3：即开彩票域；4：竞猜彩票域；
     * 5：品牌运营域；6：综合运营域；7：资金结算域；8：风险防控域；9：公共域
     */
    private Integer determineBusinessThemeDomain1(String reportName) {
        if (reportName == null || reportName.trim().isEmpty()) {
            return null;
        }

        String lowerReportName = reportName.toLowerCase();

        // 参与者域判断：代理、职员、用户、会员、兑奖人
        if (lowerReportName.contains("代理") || lowerReportName.contains("职员") ||
                lowerReportName.contains("用户") || lowerReportName.contains("会员") ||
                lowerReportName.contains("兑奖人")) {
            return 0;
        }

        // 渠道域判断：渠道、门店、市级分中心、网点、站点、销售点
        if (lowerReportName.contains("渠道") || lowerReportName.contains("门店") ||
                lowerReportName.contains("市级分中心") || lowerReportName.contains("网点") ||
                lowerReportName.contains("站点") || lowerReportName.contains("销售点")) {
            return 1;
        }

        // 乐透彩票域判断：乐透、电脑彩票、联网游戏、共彩池、奖期、奖池、调节基金、开奖、弃奖、公益金、发行费
        if (lowerReportName.contains("乐透") || lowerReportName.contains("电脑彩票") ||
                lowerReportName.contains("联网游戏") || lowerReportName.contains("共彩池") ||
                lowerReportName.contains("奖期") || lowerReportName.contains("奖池") ||
                lowerReportName.contains("调节基金") || lowerReportName.contains("开奖") ||
                lowerReportName.contains("弃奖") || lowerReportName.contains("公益金") ||
                lowerReportName.contains("发行费")) {
            return 2;
        }

        // 即开彩票域判断：即开、账期
        if (lowerReportName.contains("即开") || lowerReportName.contains("账期")) {
            return 3;
        }

        // 竞猜彩票域判断：竞猜、竞彩、高频、单场、过关
        if (lowerReportName.contains("竞猜") || lowerReportName.contains("竞彩") ||
                lowerReportName.contains("高频") || lowerReportName.contains("单场") ||
                lowerReportName.contains("过关")) {
            return 4;
        }

        // 品牌运营域判断：促销、体验券、营销
        if (lowerReportName.contains("促销") || lowerReportName.contains("体验券") ||
                lowerReportName.contains("营销")) {
            return 5;
        }

        // 综合运营域判断：综合、运营、摘要、查询、统计、排名、简报、一览表、汇总
        if (lowerReportName.contains("综合") || lowerReportName.contains("运营") ||
                lowerReportName.contains("摘要") || lowerReportName.contains("查询") ||
                lowerReportName.contains("统计") || lowerReportName.contains("排名") ||
                lowerReportName.contains("简报") || lowerReportName.contains("一览表") ||
                lowerReportName.contains("汇总")) {
            return 6;
        }

        // 资金结算域判断：资金、结算、缴款、兑奖、佣金、奖金、返奖、分配、账户、额度、平账、对账
        if (lowerReportName.contains("资金") || lowerReportName.contains("结算") ||
                lowerReportName.contains("缴款") || lowerReportName.contains("兑奖") ||
                lowerReportName.contains("佣金") || lowerReportName.contains("奖金") ||
                lowerReportName.contains("返奖") || lowerReportName.contains("分配") ||
                lowerReportName.contains("账户") || lowerReportName.contains("额度") ||
                lowerReportName.contains("平账") || lowerReportName.contains("对账")) {
            return 7;
        }

        // 风险防控域判断：风险、防控、异常、撤销、取消、解密、审计、检查、错误
        if (lowerReportName.contains("风险") || lowerReportName.contains("防控") ||
                lowerReportName.contains("异常") || lowerReportName.contains("撤销") ||
                lowerReportName.contains("取消") || lowerReportName.contains("解密") ||
                lowerReportName.contains("审计") || lowerReportName.contains("检查") ||
                lowerReportName.contains("错误")) {
            return 8;
        }

        // 公共域判断：系统、参数、角色、权限、终端、日志
        if (lowerReportName.contains("系统") || lowerReportName.contains("参数") ||
                lowerReportName.contains("角色") || lowerReportName.contains("权限") ||
                lowerReportName.contains("终端") || lowerReportName.contains("日志")) {
            return 9;
        }

        // 默认返回综合运营域
        return 6;
    }
    // 主题域常量定义
    public static final int PARTICIPANT_DOMAIN = 0;      // 参与者域
    public static final int CHANNEL_DOMAIN = 1;          // 渠道域
    public static final int LOTTO_DOMAIN = 2;            // 乐透彩票域
    public static final int INSTANT_DOMAIN = 3;          // 即开彩票域
    public static final int BETTING_DOMAIN = 4;          // 竞猜彩票域
    public static final int BRAND_DOMAIN = 5;            // 品牌运营域
    public static final int COMPREHENSIVE_DOMAIN = 6;    // 综合运营域
    public static final int FUND_DOMAIN = 7;             // 资金结算域
    public static final int RISK_DOMAIN = 8;             // 风险防控域
    public static final int PUBLIC_DOMAIN = 9;           // 公共域
    /**
     * 根据接口名称确定业务主题域类型代码
     */
    public static Integer determineBusinessThemeDomain2(String interfaceName) {
        if (interfaceName == null || interfaceName.trim().isEmpty()) {
            return null;
        }

        String lowerName = interfaceName.toLowerCase();

        // 参与者域判断：销售代表、销售员、助理、专管员、代销者
        if (lowerName.contains("销售代表") || lowerName.contains("销售员") ||
                lowerName.contains("助理") || lowerName.contains("专管员") ||
                lowerName.contains("代销者") || lowerName.contains("sr") ||
                lowerName.contains("登录状态") || lowerName.contains("登录历史") ||
                lowerName.contains("登录情况") || lowerName.contains("激活") ||
                lowerName.contains("验证状态") || lowerName.contains("承诺书")) {
            return PARTICIPANT_DOMAIN;
        }

        // 渠道域判断：门店、网点、实体店、终端、渠道
        if (lowerName.contains("门店") || lowerName.contains("网点") ||
                lowerName.contains("实体店") || lowerName.contains("终端") ||
                lowerName.contains("渠道") || lowerName.contains("销售点") ||
                lowerName.contains("开机") || lowerName.contains("转发") ||
                lowerName.contains("高关注") || lowerName.contains("宣传素材") ||
                lowerName.contains("实体渠道") || lowerName.contains("合作商户")) {
            return CHANNEL_DOMAIN;
        }

        // 乐透彩票域判断：乐透、大乐透、七星彩、奖期、奖池、开奖
        if (lowerName.contains("乐透") || lowerName.contains("大乐透") ||
                lowerName.contains("七星彩") || lowerName.contains("奖期") ||
                lowerName.contains("奖池") || lowerName.contains("开奖") ||
                lowerName.contains("中奖") || lowerName.contains("奖级") ||
                lowerName.contains("弃奖") || lowerName.contains("热号") ||
                lowerName.contains("销量") || lowerName.contains("奖号码") ||
                lowerName.contains("大奖") || lowerName.contains("公益金")) {
            return LOTTO_DOMAIN;
        }

        // 即开彩票域判断：即开、箱包、激活、兑奖票
        if (lowerName.contains("即开") || lowerName.contains("箱包") ||
                lowerName.contains("激活") || lowerName.contains("兑奖票") ||
                lowerName.contains("库存") || lowerName.contains("出入库") ||
                lowerName.contains("促销兑奖") || lowerName.contains("账期") ||
                lowerName.contains("账单") || lowerName.contains("周转时长") ||
                lowerName.contains("面值列表") || lowerName.contains("上市时间")) {
            return INSTANT_DOMAIN;
        }

        // 竞猜彩票域判断：竞彩、北单、名次、限号
        if (lowerName.contains("竞彩") || lowerName.contains("北单") ||
                lowerName.contains("名次") || lowerName.contains("限号") ||
                lowerName.contains("玩法") || lowerName.contains("时段") ||
                lowerName.contains("取消票") || lowerName.contains("竞猜") ||
                lowerName.contains("高频") || lowerName.contains("单场") ||
                lowerName.contains("过关") || lowerName.contains("名次")) {
            return BETTING_DOMAIN;
        }

        // 品牌运营域判断：促销、活动、奖品、营销、抽奖
        if (lowerName.contains("促销") || lowerName.contains("活动") ||
                lowerName.contains("奖品") || lowerName.contains("营销") ||
                lowerName.contains("抽奖") || lowerName.contains("体验券") ||
                lowerName.contains("核销") || lowerName.contains("幸运抽奖") ||
                lowerName.contains("宣传物料") || lowerName.contains("票面促销") ||
                lowerName.contains("幸运顾客") || lowerName.contains("安卓终端") ||
                lowerName.contains("兑奖明细") || lowerName.contains("中奖兑奖")) {
            return BRAND_DOMAIN;
        }

        // 资金结算域判断：缴款、支付、额度、账单、结算、账户、交易
        if (lowerName.contains("缴款") || lowerName.contains("支付") ||
                lowerName.contains("额度") || lowerName.contains("账单") ||
                lowerName.contains("结算") || lowerName.contains("账户") ||
                lowerName.contains("交易") || lowerName.contains("转账") ||
                lowerName.contains("佣金") || lowerName.contains("奖金") ||
                lowerName.contains("返奖") || lowerName.contains("对账") ||
                lowerName.contains("平账") || lowerName.contains("财务") ||
                lowerName.contains("日终复核") || lowerName.contains("银行交易") ||
                lowerName.contains("赠票") || lowerName.contains("移动支付")) {
            return FUND_DOMAIN;
        }

        // 风险防控域判断：风险、异常、撤销、取消、监控、关注
        if (lowerName.contains("风险") || lowerName.contains("异常") ||
                lowerName.contains("撤销") || lowerName.contains("取消") ||
                lowerName.contains("监控") || lowerName.contains("关注") ||
                lowerName.contains("防控") || lowerName.contains("解密") ||
                lowerName.contains("审计") || lowerName.contains("错误") ||
                lowerName.contains("限号") || lowerName.contains("负值") ||
                lowerName.contains("复制票") || lowerName.contains("取消票") ||
                lowerName.contains("大额票") || lowerName.contains("销量增长") ||
                lowerName.contains("销量下降") || lowerName.contains("返奖率") ||
                lowerName.contains("投注") || lowerName.contains("指标")) {
            return RISK_DOMAIN;
        }

        // 公共域判断：游戏、奖期、省、市、县、兑奖处、值域、信息表
        if (lowerName.contains("游戏") || lowerName.contains("奖期") ||
                lowerName.contains("省") || lowerName.contains("市") ||
                lowerName.contains("县") || lowerName.contains("兑奖处") ||
                lowerName.contains("值域") || lowerName.contains("信息表") ||
                lowerName.contains("区域") || lowerName.contains("列表") ||
                lowerName.contains("报表") || lowerName.contains("接口") ||
                lowerName.contains("查询") || lowerName.contains("详情") ||
                lowerName.contains("统计") || lowerName.contains("汇总") ||
                lowerName.contains("排名") || lowerName.contains("简报") ||
                lowerName.contains("分布") || lowerName.contains("明细") ||
                lowerName.contains("摘要") || lowerName.contains("结果") ||
                lowerName.contains("号码") || lowerName.contains("热号") ||
                lowerName.contains("同步状态") || lowerName.contains("使用记录")) {
            return PUBLIC_DOMAIN;
        }

        // 默认返回综合运营域
        return COMPREHENSIVE_DOMAIN;
    }
}